home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 32 / advsys.zip / ADVEXE.C < prev    next >
Text File  |  1987-06-28  |  6KB  |  330 lines

  1. /* advexe.c - adventure code executer */
  2. /*
  3.     Copyright (c) 1986, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include "advint.h"
  8. #include "advdbs.h"
  9.  
  10. /* external variables */
  11. extern char line[];
  12. extern int nouns[],*adjectives[];
  13.  
  14. /* local variables */
  15. int pc,opcode,p2,p3,sts;
  16. int stack[STKSIZE],*sp,*fp,*top;
  17. long rseed = 1L;
  18.  
  19. /* external routines */
  20. extern long time();
  21.  
  22. /* execute - execute adventure code */
  23. int execute(code)
  24.   int code;
  25. {
  26.     /* setup initial program counter */
  27.     if ((pc = code) == NIL)
  28.     return (CHAIN);
  29.  
  30.     /* initialize */
  31.     sp = fp = top = stack + STKSIZE;
  32.  
  33.     /* execute the code */
  34.     for (sts = 0; sts == 0; )
  35.     exe_one();
  36.  
  37.     return (sts);
  38. }
  39.  
  40. /* exe_one - execute one instruction */
  41. exe_one()
  42. {
  43.     /* get the opcode */
  44.     opcode = getcbyte(pc); pc++;
  45.  
  46.     /* execute the instruction */
  47.     switch (opcode) {
  48.     case OP_CALL:
  49.         *--sp = getboperand();
  50.         *--sp = pc;
  51.         *--sp = (int)(top - fp);
  52.         fp = sp;
  53.         pc = getafield(fp[fp[2]+3],A_CODE);
  54.         break;
  55.     case OP_SEND:
  56.         *--sp = getboperand();
  57.         *--sp = pc;
  58.         *--sp = (int)(top - fp);
  59.         fp = sp;
  60.         if (p2 = fp[fp[2]+3])
  61.             p2 = getofield(p2,O_CLASS);
  62.         else
  63.             p2 = fp[fp[2]+2];
  64.         if (p2 && (p2 = getp(p2,fp[fp[2]+1]))) {
  65.             pc = getafield(p2,A_CODE);
  66.             break;
  67.         }
  68.         *sp = NIL;
  69.         /* return NIL if there is no method for this message */
  70.     case OP_RETURN:
  71.         if (fp == top)
  72.             sts = CHAIN;
  73.         else {
  74.             p2 = *sp;
  75.             sp = fp;
  76.             fp = top - *sp++;
  77.             pc = *sp++;
  78.             p3 = *sp++;
  79.             sp += p3;
  80.             *sp = p2;
  81.         }
  82.         break;
  83.     case OP_TSPACE:
  84.         sp -= getboperand();
  85.         break;
  86.     case OP_TMP:
  87.         p2 = getboperand();
  88.         *sp = fp[-p2-1];
  89.         break;
  90.     case OP_TSET:
  91.         p2 = getboperand();
  92.         fp[-p2-1] = *sp;
  93.         break;
  94.     case OP_ARG:
  95.         p2 = getboperand();
  96.         if (p2 >= fp[2])
  97.             advfatal("too few arguments");
  98.         *sp = fp[p2+3];
  99.         break;
  100.     case OP_ASET:
  101.         p2 = getboperand();
  102.         if (p2 >= fp[2])
  103.             advfatal("too few arguments");
  104.         fp[p2+3] = *sp;
  105.         break;
  106.     case OP_BRT:
  107.         pc = (*sp ? getwoperand() : pc+2);
  108.         break;
  109.     case OP_BRF:
  110.         pc = (*sp ? pc+2 : getwoperand());
  111.         break;
  112.     case OP_BR:
  113.         pc = getwoperand();
  114.         break;
  115.     case OP_T:
  116.         *sp = T;
  117.         break;
  118.     case OP_NIL:
  119.         *sp = NIL;
  120.         break;
  121.     case OP_PUSH:
  122.         *--sp = NIL;
  123.         break;
  124.     case OP_NOT:
  125.         *sp = (*sp ? NIL : T);
  126.         break;
  127.     case OP_ADD:
  128.         p2 = *sp++;
  129.         *sp += p2;
  130.         break;
  131.     case OP_SUB:
  132.         p2 = *sp++;
  133.         *sp -= p2;
  134.         break;
  135.     case OP_MUL:
  136.         p2 = *sp++;
  137.         *sp *= p2;
  138.         break;
  139.     case OP_DIV:
  140.         p2 = *sp++;
  141.         *sp = (p2 == 0 ? 0 : *sp / p2);
  142.         break;
  143.     case OP_REM:
  144.         p2 = *sp++;
  145.         *sp = (p2 == 0 ? 0 : *sp % p2);
  146.         break;
  147.     case OP_BAND:
  148.         p2 = *sp++;
  149.         *sp &= p2;
  150.         break;
  151.     case OP_BOR:
  152.         p2 = *sp++;
  153.         *sp |= p2;
  154.         break;
  155.     case OP_BNOT:
  156.         *sp = ~*sp;
  157.         break;
  158.     case OP_LT:
  159.         p2 = *sp++;
  160.         *sp = (*sp < p2 ? T : NIL);
  161.         break;
  162.     case OP_EQ:
  163.         p2 = *sp++;
  164.         *sp = (*sp == p2 ? T : NIL);
  165.         break;
  166.     case OP_GT:
  167.         p2 = *sp++;
  168.         *sp = (*sp > p2 ? T : NIL);
  169.         break;
  170.     case OP_LIT:
  171.         *sp = getwoperand();
  172.         break;
  173.     case OP_SPLIT:
  174.         *sp = getboperand();
  175.         break;
  176.     case OP_SNLIT:
  177.         *sp = -getboperand();
  178.         break;
  179.     case OP_VAR:
  180.         *sp = getvalue(getwoperand());
  181.         break;
  182.     case OP_SVAR:
  183.         *sp = getvalue(getboperand());
  184.         break;
  185.     case OP_SET:
  186.         setvalue(getwoperand(),*sp);
  187.         break;
  188.     case OP_SSET:
  189.         setvalue(getboperand(),*sp);
  190.         break;
  191.     case OP_GETP:
  192.         p2 = *sp++;
  193.         *sp = getp(*sp,p2);
  194.         break;
  195.     case OP_SETP:
  196.         p3 = *sp++;
  197.         p2 = *sp++;
  198.         *sp = setp(*sp,p2,p3);
  199.         break;
  200.     case OP_PRINT:
  201.         print(*sp);
  202.         break;
  203.     case OP_PNUMBER:
  204.             pnumber(*sp);
  205.             break;
  206.     case OP_PNOUN:
  207.         show_noun(*sp);
  208.         break;
  209.     case OP_TERPRI:
  210.         trm_chr('\n');
  211.         break;
  212.     case OP_FINISH:
  213.         sts = FINISH;
  214.         break;
  215.     case OP_CHAIN:
  216.         sts = CHAIN;
  217.         break;
  218.     case OP_ABORT:
  219.         sts = ABORT;
  220.         break;
  221.     case OP_EXIT:
  222.         advpause();
  223.         trm_done();
  224.         exit(0);
  225.         break;
  226.     case OP_YORN:
  227.         trm_get(line);
  228.         *sp = (line[0] == 'Y' || line[0] == 'y' ? T : NIL);
  229.             break;
  230.     case OP_CLASS:
  231.         *sp = getofield(*sp,O_CLASS);
  232.         break;
  233.     case OP_MATCH:
  234.         p2 = *sp++;
  235.         *sp = (match(*sp,nouns[p2-1],adjectives[p2-1]) ? T : NIL);
  236.         break;
  237.     case OP_SAVE:
  238.         *sp = db_save();
  239.         break;
  240.     case OP_RESTORE:
  241.         *sp = db_restore();
  242.         break;
  243.     case OP_RESTART:
  244.         *sp = db_restart();
  245.         break;
  246.     case OP_RAND:
  247.         *sp = getrand(*sp);
  248.         break;
  249.     case OP_RNDMIZE:
  250.         setrand(time(0L));
  251.         *sp = NIL;
  252.         break;
  253.     default:
  254.         if (opcode >= OP_XVAR && opcode < OP_XSET)
  255.         *sp = getvalue(opcode - OP_XVAR);
  256.         else if (opcode >= OP_XSET && opcode < OP_XPLIT)
  257.         setvalue(opcode - OP_XSET,*sp);
  258.         else if (opcode >= OP_XPLIT && opcode < OP_XNLIT)
  259.         *sp = opcode - OP_XPLIT;
  260.         else if (opcode >= OP_XNLIT && opcode < 256)
  261.         *sp = OP_XNLIT - opcode;
  262.         else
  263.         trm_str("Bad opcode\n");
  264.         break;
  265.     }
  266. }
  267.  
  268. /* getboperand - get data byte */
  269. int getboperand()
  270. {
  271.     int data;
  272.     data = getcbyte(pc); pc += 1;
  273.     return (data);
  274. }
  275.  
  276. /* getwoperand - get data word */
  277. int getwoperand()
  278. {
  279.     int data;
  280.     data = getcword(pc); pc += 2;
  281.     return (data);
  282. }
  283.  
  284. /* print - print a message */
  285. print(msg)
  286.   int msg;
  287. {
  288.     int ch;
  289.  
  290.     msg_open(msg);
  291.     while (ch = msg_byte())
  292.     trm_chr(ch);
  293. }
  294.  
  295. /* pnumber - print a number */
  296. pnumber(n)
  297.   int n;
  298. {
  299.     char buf[10];
  300.  
  301.     sprintf(buf,"%d",n);
  302.     trm_str(buf);
  303. }
  304.  
  305. /* getrand - get a random number between 0 and n-1 */
  306. int getrand(n)
  307.   int n;
  308. {
  309.     long k1;
  310.  
  311.     /* make sure we don't get stuck at zero */
  312.     if (rseed == 0L) rseed = 1L;
  313.  
  314.     /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
  315.     k1 = rseed / 127773L;
  316.     if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
  317.     rseed += 2147483647L;
  318.  
  319.     /* return a random number between 0 and n-1 */
  320.     return ((int)(rseed % (long)n));
  321. }
  322.  
  323. /* setrand - set the random number seed */
  324. setrand(n)
  325.   long n;
  326. {
  327.     rseed = n;
  328. }
  329.  
  330.